package com.xx.netty.server.handler;

import com.xx.dk.tbsalling.aismessages.AISInputStreamReader;
import com.xx.dk.tbsalling.aismessages.ais.exceptions.UnsupportedMessageType;
import com.xx.dk.tbsalling.aismessages.ais.messages.handler.AISMessageHandler;
import com.xx.dk.tbsalling.aismessages.ais.messages.handler.AISMessageHandlerConfig;
import com.xx.dk.tbsalling.aismessages.ais.messages.types.AISMessageType;
import com.xx.netty.server.AisServer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;

/**
 * @description: ais message handler
 * @author: xx
 * @Date 2023/7/14 16:16
 * @version: 1.0
 */
@Slf4j
@ChannelHandler.Sharable
@Component
public class AisServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 处理接收到的消息
     * 当通道读取到数据时，该方法会被调用
     * 它首先检查缓冲区中是否有可读的字节，并且第一个字节是否为33，这是AIS消息的标识
     * 如果是AIS消息，则创建一个AISInputStreamReader来解析消息，并根据消息类型选择相应的处理程序
     *
     * @param ctx 通道处理上下文
     * @param msg 接收到的消息，预期是一个ByteBuf实例
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg){
        ByteBuf buf = (ByteBuf) msg;
        try {
            if (buf.readableBytes() > 0 && buf.getByte(0) == 33) {
                //System.out.println("========" + buf.toString(Charset.defaultCharset()));
                AISInputStreamReader reader = new AISInputStreamReader(new ByteArrayInputStream(ByteBufUtil.getBytes(buf)), message -> {
                    //get message type
                    AISMessageType messageType = message.getMessageType();
                    if (messageType != null) {
                        AISMessageHandler handler = AISMessageHandlerConfig.handlers.get(messageType);
                        if (handler != null) {
                            //process messages
                            handler.handle(message);
                        } else {
                            throw new UnsupportedMessageType(messageType.getCode());
                        }
                    } else {
                        System.out.println("Received unknown message type: " + message);
                    }
                });
                //start parsing the AIS data
                reader.run();
            }
        } finally {
            buf.release();
        }
    }

    // 当连接断开时触发 inactive 事件
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        AisServer.clientChannel = null;
        log.debug("{} 已经断开", ctx.channel());
    }

    // 当出现异常时触发
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        AisServer.clientChannel = null;
        log.error("{} 已经异常断开 异常是{}", ctx.channel(), cause.getMessage());
        //cause.printStackTrace();
    }
}
